using System;
using System.Collections.Generic;
using System.Resources;
using UnityEngine;

namespace LFramework
{
    public enum UIResourceType
    {
        //ui主窗口
        UIWindow,

        //ui子窗口
        UIPanel,
    }

    public class UiResourcesInfo
    {
        public UIResourceType eType = UIResourceType.UIWindow;
        public string StrResourcePath { get; set; }
        public UnityEngine.Object ResObj { get; set; }
    }

    public class UICtrlBase
    {
        public virtual UIGroupType GroupType => UIGroupType.Normal;

        private bool m_Showing = false;
        protected UIWindow m_UIWindow = null;
        protected GameObject m_UIWindowGo = null;
        protected Dictionary<string,UiResourcesInfo> m_NeedResourcesDic = new Dictionary<string,UiResourcesInfo>();
        private Dictionary<string, UnityEngine.Object> m_AssetsDic = new Dictionary<string, UnityEngine.Object>();
        private Dictionary<string, Action<string,UnityEngine.Object>> m_AssetsLoadCBDic = new Dictionary<string, Action<string, UnityEngine.Object>>();
        //主窗口
        protected UiResourcesInfo m_MainWindowInfo = null;
        //资源加载完成数量
        protected int ResourcesCompleteCount = 0;

        private int m_WindowOrder;

        public int WindowOrder
        {
            get { return m_WindowOrder; }
            set
            {
                m_WindowOrder = value;
                if (m_UIWindow != null)
                {
                    m_UIWindow.SetCanvasOrder(m_WindowOrder);
                }
            }
        }

        public virtual void Open()
        {
            if (m_Showing)
                return;

            m_Showing = true;

            GameEntry.UI.AddUI(this);
        }

        public void DoOpen()
        {
            foreach (KeyValuePair<string,UiResourcesInfo> item in m_NeedResourcesDic)
            {
                if (item.Value.ResObj != null)
                {
                    ResourcesCompleteCount++;
                    continue;
                }
                GameEntry.AssetsLoader.LoadAssetAsync(item.Value.StrResourcePath,HandleUIResourceOK);
            }
        }

        public virtual void Close()
        {
            if (!m_Showing)
            {
                return;
            }

            m_Showing = false;
            GameEntry.UI.RemoveUI(this);
            
            if (m_UIWindow != null)
            {
                m_UIWindow.Release();
                m_UIWindow = null;
            }
            
            if (m_UIWindowGo != null)
            {
                GameEntry.Pool.GameObjectPool.Enspawn(m_UIWindowGo);
                m_UIWindowGo = null;
            }
            
            foreach (KeyValuePair<string,UiResourcesInfo> item in m_NeedResourcesDic)
            {
                if (item.Value.ResObj == null)
                    GameEntry.AssetsLoader.UnLoadAssetAsync(item.Value.StrResourcePath,HandleUIResourceOK);
                else
                    GameEntry.AssetsLoader.UnLoadAssetSync(item.Value.StrResourcePath);
            }

            foreach (var item in m_AssetsDic)
                GameEntry.AssetsLoader.UnLoadAssetSync(item.Key);

            m_NeedResourcesDic.Clear();
            m_AssetsDic.Clear();
            m_AssetsLoadCBDic.Clear();
            ResourcesCompleteCount = 0;
            m_MainWindowInfo = null;
        }

        /// <summary>
        /// 打开界面前需要加载的资源
        /// </summary>
        /// <param name="strPath"></param>
        /// <param name="eType"></param>
        protected void AddNeedResources(string strPath, UIResourceType eType)
        {
            UiResourcesInfo info;
            if(m_NeedResourcesDic.TryGetValue(strPath,out info))
                return;

            info = new UiResourcesInfo();
            info.StrResourcePath = strPath;
            info.eType = eType;
            m_NeedResourcesDic[strPath] = info;
            
            //设置主窗口
            if (eType == UIResourceType.UIWindow)
            {
                if (m_MainWindowInfo == null)
                    m_MainWindowInfo = info;
                else
                    GameEntry.Log("主窗口 只允许一个 path:: " + strPath);
            }
        }
        
        /// <summary>
        /// 资源加载完成
        /// </summary>
        /// <param name="strPath"></param>
        /// <param name="objResource"></param>
        private void HandleUIResourceOK(string strPath, UnityEngine.Object objResource)
        {
            if (!m_Showing)
            {
                return;
            }
            
            UiResourcesInfo info;
            if (!m_NeedResourcesDic.TryGetValue(strPath, out info))
            {
                GameEntry.Log("资源加载完成，但未找到需要加载Info信息");
                return;
            }

            if (objResource != null)
            {
                ResourcesCompleteCount++;
                info.ResObj = objResource;
            }
            else
            {
                Close();
                GameEntry.Log("加载资源为null path: " + strPath); 
            }
            
            // 每下完事一个就检查一下是否都搞定了
            CheckAllResInfoFinish();
        }
        
        /// <summary>
        /// 检查是否所有资源加载完成
        /// </summary>
        private void CheckAllResInfoFinish()
        {
            if(ResourcesCompleteCount != m_NeedResourcesDic.Count)
                return;
            OnUiLoaded();
        }

        /// <summary>
        /// 真正加载ui 的地方
        /// </summary>
        /// <param name="bLoaded"></param>
        private void OnUiLoaded()
        {
            if(m_UIWindow != null)
                return;
            
            if (m_MainWindowInfo == null)
            {
                GameEntry.LogError("load 主ui error: ");
                return;
            }

            m_UIWindowGo = GameEntry.Pool.GameObjectPool.Spawn(m_MainWindowInfo.StrResourcePath, GameEntry.UI.CanvasDic[GroupType]);
            RectTransform rectTrans = m_UIWindowGo.GetComponent<RectTransform>();

            m_UIWindowGo.transform.localScale = Vector3.one;
            m_UIWindowGo.transform.localPosition = Vector3.zero;
            // m_UIWindowGo.transform.localEulerAngles = Vector3.zero;
            rectTrans.anchorMin = Vector2.zero;
            rectTrans.anchorMax = Vector2.one;
            rectTrans.offsetMax = Vector2.zero;
            rectTrans.offsetMin = Vector2.zero;
            
            m_UIWindow = m_UIWindowGo.GetComponent<UIWindow>();

            if (m_UIWindow == null)
            {
                GameEntry.LogError("没有发现UIWindow 组件: " + m_MainWindowInfo.StrResourcePath);
                return;
            }

            GameEntry.UI.RefreshCanvasOrder();
            m_UIWindow.SetUICtrl(this);
            m_UIWindow.Init();
        }

        #region 加载panel 相关接口
        public GameObject AddPanel(string panelPath, Transform parent)
        {
            GameObject panelGo = null;
            foreach (var item in m_NeedResourcesDic)
            {
                if (item.Key == panelPath) 
                {
                    panelGo = GameEntry.Pool.GameObjectPool.Spawn(panelPath, parent);
                    panelGo.transform.localScale = Vector3.one;
                    panelGo.transform.localPosition = Vector3.zero;

                    break;
                }
            }
            
            if (panelGo == null)
                GameEntry.LogError(this + " load panel fail with PanelPath:" + panelPath);
            return panelGo;
        }

        public void RemovePanel(GameObject go)
        {
            if(go != null)
                GameEntry.Pool.GameObjectPool.Enspawn(go);
        }
        #endregion

        #region 其他未预加载资源 加载相关接口

        public void GetAsset(string strPath, Action<string, UnityEngine.Object> loadCB) 
        {
            if (m_AssetsDic.TryGetValue(strPath, out UnityEngine.Object obj)) 
            {
                loadCB?.Invoke(strPath, obj);
                return;
            }

            if (m_AssetsLoadCBDic.TryGetValue(strPath, out Action<string, UnityEngine.Object> cb))
                cb += loadCB;
            else
                m_AssetsLoadCBDic[strPath] = loadCB;

            GameEntry.AssetsLoader.LoadAssetAsync(strPath, OnAssetLoaded);
        }

        private void OnAssetLoaded(string strPath, UnityEngine.Object obj)
        {
            if (!m_Showing)
            {
                GameEntry.AssetsLoader.UnLoadAssetSync(strPath);
                return;
            }

            m_AssetsDic[strPath] = obj;

            if (m_AssetsLoadCBDic.ContainsKey(strPath))
            {
                if (m_AssetsLoadCBDic[strPath] != null)
                {
                    m_AssetsLoadCBDic[strPath](strPath, obj);
                }

                m_AssetsLoadCBDic.Remove(strPath);
            }
        }
        #endregion
    }
}
